package com.ll3d.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Timer;
import java.util.concurrent.TimeUnit;

/**
 * @Author:linchong
 * @CreateTime:2020-07-15 19:09
 * @Description:
 */
@Slf4j
@Controller
public class AdminController {


	@GetMapping("/v1")
	public String login(Model model){
		return "v1/login";
	}

	@GetMapping("v1/index")
	public String index(Model model){
		model.addAttribute("key","test");
		return "v1/index";
	}

	@GetMapping("/v1/logout")
	public String logout(HttpServletRequest request){
		request.getSession().invalidate();
		return "v1/login";
	}

	/**
	 * 基于授权码模式
	 * @return
	 */
	@GetMapping("/v2")
	public String login2(){
		return "/v2/index";
	}

	@GetMapping("/v2/index")
	public String index2(){
		return "/v2/index";
	}

	@GetMapping("/v2/logout")
	public String logout(HttpSession session){
		session.invalidate();
		return "/v2/index";
	}

	@GetMapping
	public String login3(){
		return "/v3/index";
	}

	@GetMapping("/index")
	public String index3(){
		return "/v3/index";
	}

	@GetMapping("/logout")
	public String logout3(HttpSession session){
		session.invalidate();
		return "/v3/index";
	}
	/**
	 * 授权码模式下，引导用户去认证服务器登录，这个应该放到前端服务器上做，这里没有，所以写在这里，之后应该写在前端
	 * state参数用来记录用户登录前想要跳转的页面，方便用户认证成功后跳转页面
	 *
	 * 这里的认证服务器的登录页面可以自定义，重写认证服务器的安全配置的方法即可，
	 * 即重写继承了WebSecurityConfigureAdapter类的configure(HttpSecurity http)方法，指定登录页面即可
	 * @param response
	 */
	@GetMapping("/toAuthLogin")
	public void toAuthLogin(HttpServletResponse response) throws IOException {

		String redirectOauthUrl = "http://auth.chong.com:9090/oauth/authorize?"
				+"client_id=admin&"
				+"redirect_uri=http://admin.chong.com:8080/oauth/callback&"
				+"response_type=code&"
				+"state=/index";
		response.sendRedirect(redirectOauthUrl);
	}

	/**
	 * 授权回调的地址，需要在数据库中有对应的配置，authorized_grant_types新增authorization_code授权码模式，
	 * 填写授权地址：http://admin.chong.com:8080/oauth/callback，设置autoapprove,即是否自动授权，是，填写true,
	 * 如果填写read，则只有read权限
	 * @param code
	 * @param state
	 * @param session
	 * @return
	 */
	@GetMapping("/oauth/callback")
	public String callback(@RequestParam String code,String state,HttpSession session){
		log.info("code:{},state:{}",code,state);
		//回调成功后，认证服务器校验token
		String oauthServiceUrl = "http://gateway.chong.com:9070/token/oauth/token";
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		//已注册的网关id,需要提前在数据库中注册
		headers.setBasicAuth("admin","123456");
		MultiValueMap<String,String> params = new LinkedMultiValueMap<>();
		params.add("code",code);
		params.add("grant_type","authorization_code");
		//认证服务器中对比客户端信息的redirect_uri和这里的是否相同，不一致报错,
		//跳转链接是明文传输的，防止别人串改跳转链接，跳转到对应的网站上，获取授权码信息
		//http://admin.chong.com:8080/oauth/callback
		params.add("redirect_uri","http://admin.chong.com:8080/oauth/callback");
		HttpEntity<MultiValueMap<String,String>> entiy = new HttpEntity<>(params,headers);
		ResponseEntity<AccessToken> response = restTemplate.exchange(oauthServiceUrl,HttpMethod.POST,
				entiy,AccessToken.class);

		AccessToken accessToken = response.getBody();
		LocalDateTime rightNow = LocalDateTime.now();
		rightNow = rightNow.plusSeconds(accessToken.getExpires_in());
		accessToken.setExpireTime(rightNow);

		session.setAttribute("chong_token",accessToken);
		return "redirect:/index";

	}


	private RestTemplate restTemplate = new RestTemplate();

	/**
	 * 处理登录请求，调用网关，获取token ，获取后放在了 前端服务器的session里
	 * @param username
	 * @param password
	 * @param request
	 * @return
	 */
	@PostMapping("/login")
	@ResponseBody
	public Result login(@RequestParam String username,@RequestParam String password, HttpServletRequest request){

		String oauthServiceUrl = "http://gateway.chong.com:9070/token/oauth/token";
		HttpHeaders headers = new HttpHeaders();
		//请求内容格式
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		//请求信息,网关的clientid和clientSecret
		headers.setBasicAuth("admin","123456");
		//填充请求参数
		//注意这里只能用它
		MultiValueMap<String,String> params = new LinkedMultiValueMap<>();
		params.add("username",username);
		params.add("password",password);
		params.add("grant_type","password");
		params.add("scope","read write");

		HttpEntity<MultiValueMap<String,String>> entity = new HttpEntity<>(params,headers);
		//发送请求
		ResponseEntity<AccessToken> response =  restTemplate.exchange(oauthServiceUrl, HttpMethod.POST,entity, AccessToken.class);
		log.info("响应信息为：{}",response.getBody());
		request.getSession().setAttribute("chong_token",response.getBody());
		return Result.builder().data(true).msg("success").build();
	}


	@GetMapping("/me")
	@ResponseBody
	public Boolean currentUserInfo(HttpServletRequest request,Model model){

		HttpSession session = request.getSession();
		if(session.getAttribute("chong_token")==null){
			return false;
		}
		return true;

	}

}
